﻿// -----------------------------------------------------------------------
// <copyright file="PushStatsRepository.cs" company="Zen Design Corp">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Zen.BlackBerry.Push.Repositories
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Runtime.Caching;
	using Zen.BlackBerry.Push.DataAccess;
	using Zen.BlackBerry.Push.Stats;

	/// <summary>
	/// TODO: Update summary.
	/// </summary>
	public class PushStatsRepository : CachingRepository, IPushStatsRepository
	{
		public PushStatsRepository()
		{
		}

		private void AddPushStatsCore(PushStats pushStats)
		{
			DbPushApplication dbApplication = ObjectContext.DbPushApplications
				.First((item) => item.RimApplicationId == pushStats.ApplicationId);
			DbPushStatistics dbStats =
				new DbPushStatistics
				{
					Application = dbApplication,
					DailyPushCount = pushStats.DailyPushCount,
					DailyPushCountDate = DateTime.UtcNow,
					RunningContentSum = pushStats.RunningContentSum,
					RunningPushCount = pushStats.RunningPushCount
				};
			ObjectContext.DbPushStatistics.AddObject(dbStats);
		}

		private bool UpdatePushStatsCore(PushStats pushStats)
		{
			bool result = false;
			DbPushStatistics dbStats = ObjectContext.DbPushStatistics
				.Include("Application")
				.FirstOrDefault((item) => item.Application.RimApplicationId == pushStats.ApplicationId);
			if (dbStats != null)
			{
				if (dbStats.DailyPushCountDate.Date == pushStats.DailyPushCountDate.Date)
				{
					dbStats.DailyPushCount += pushStats.DailyPushCount;
				}
				else
				{
					dbStats.DailyPushCount = pushStats.DailyPushCount;
				}
				dbStats.DailyPushCountDate = pushStats.DailyPushCountDate;

				dbStats.RunningContentSum += pushStats.RunningContentSum;
				dbStats.RunningPushCount += pushStats.RunningPushCount;
				result = true;
			}
			return result;
		}

		#region IPushStatsRepository Members

		public void AddPushStats(PushStats pushStats)
		{
			AddPushStatsCore(pushStats);
			ObjectContext.SaveChanges();
		}

		public void BatchUpdatePushStats(ICollection<PushStats> pushStats)
		{
			foreach (var stat in pushStats)
			{
				if (!UpdatePushStatsCore(stat))
				{
					AddPushStatsCore(stat);
				}
			}
			ObjectContext.SaveChanges();
		}

		public PushStats GetPushStats(string pushApplicationId, bool preferUseCache)
		{
			string cacheKey = GetCacheKey(pushApplicationId);
			PushStats stats = null;
			if (preferUseCache)
			{
				stats = (PushStats)Cache.Get(cacheKey);
			}

			if (stats == null)
			{
				stats = ObjectContext.DbPushStatistics
					.Include("Application")
					.Where((item) => item.Application.RimApplicationId == pushApplicationId)
					.Select((item) =>
						new PushStats
						{
							ApplicationId = pushApplicationId,
							DailyPushCount = item.DailyPushCount,
							DailyPushCountDate = item.DailyPushCountDate,
							RunningContentSum = item.RunningContentSum,
							RunningPushCount = item.RunningPushCount
						})
					.First();

				// If we tried the cache earlier or the item does not exist in
				//	the cache, then add it now
				if (preferUseCache || !Cache.Contains(cacheKey))
				{
					Cache.Add(
						cacheKey, stats,
						new CacheItemPolicy
						{
							SlidingExpiration = TimeSpan.FromMinutes(5)
						});
				}
			}
			return stats;
		}

		public void ResetRunningContentSum(string pushApplicationId)
		{
			PushStats stats = GetCachedItem<PushStats>(pushApplicationId);
			if (stats != null)
			{
				stats.RunningContentSum = 0;
			}

			DbPushStatistics dbStats = ObjectContext.DbPushStatistics
				.Include("Application")
				.FirstOrDefault((item) => item.Application.RimApplicationId == pushApplicationId);
			if (dbStats != null)
			{
				dbStats.RunningContentSum = 0;
				ObjectContext.SaveChanges();
			}
		}

		public void ResetRunningPushCount(string pushApplicationId)
		{
			PushStats stats = GetCachedItem<PushStats>(pushApplicationId);
			if (stats != null)
			{
				stats.RunningPushCount = 0;
			}

			DbPushStatistics dbStats = ObjectContext.DbPushStatistics
				.Include("Application")
				.FirstOrDefault((item) => item.Application.RimApplicationId == pushApplicationId);
			if (dbStats != null)
			{
				dbStats.RunningPushCount = 0;
				ObjectContext.SaveChanges();
			}
		}

		public void UpdateCache(PushStats pushStats)
		{
			PushStats cachedStats = GetCachedItem<PushStats>(pushStats.ApplicationId);
			if (cachedStats != null)
			{
				if (cachedStats.DailyPushCountDate.Date == pushStats.DailyPushCountDate.Date)
				{
					cachedStats.DailyPushCount += pushStats.DailyPushCount;
				}
				else
				{
					cachedStats.DailyPushCount = pushStats.DailyPushCount;
				}
				cachedStats.DailyPushCountDate = pushStats.DailyPushCountDate;

				cachedStats.RunningContentSum += pushStats.RunningContentSum;
				cachedStats.RunningPushCount += pushStats.RunningPushCount;
			}
		}

		public bool UpdatePushStats(PushStats pushStats)
		{
			bool result = UpdatePushStatsCore(pushStats);
			if (result)
			{
				ObjectContext.SaveChanges();
			}
			return result;
		}

		#endregion
	}
}
